平时工作中,能用到的类基本都是可变的,无论是实例的属性,还是类的属性,也正是因为这样,所以python也是一个“鸭子类型”的编程语言。
今天给大家看看python类的不同面,“不可变”
首先先来看下普通的类,我们都是怎么操作的
>>> class A:... pass... >>> a = A()>>> a.abcTraceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'A' object has no attribute 'abc'>>> a.abc = 1>>> a.abc1
上面这段代码很简单,对于你来说一定也不陌生,在我们需要的时候动态的添加属性,这也是我们用python很爽的地方。
那么这个时候,如果这个类是个关键类,或者只是个只读类,如何才能组织这些动态的,不受控制的添加呢?
>>> class B:... __slots__ = ['papapa']... ... def __init__(self, papapa):... super().__setattr__('papapa', papapa)... ... def __setattr__(self, name, value):... raise AttributeError(f'{self.__class__} has no attribute {name}')... >>> b = B('fanbingbing')>>> b.papapa'fanbingbing'>>> b.papapa = 'linzhiling'Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 8, in __setattr__AttributeError: <class 'B'> has no attribute papapa>>> b.__dict__Traceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'B' object has no attribute '__dict__'>>> b.abc = 123Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 8, in __setattr__AttributeError: <class 'B'> has no attribute abc
这里的关键点有2个:
__slots__ 方法,在类中,使用__slots__方法可以控制类的属性和方法,在定义完类后,我对b.__dict__做了一个查询,目的就是告诉大家,__slots__会替换掉__dict__,而__dict__就是类和实例存储属性的地方。
但是大家一定要注意,使用__slots__是有风险的,由于强制限制了__dict__的使用,那么你要添加任何方法和属性的时候就得重写这个类了,并且继承B类的子类,也需要重写__slots__方法。
所以通过__slots__,我们限制了实例属性的任意添加。
__setattr__方法,我们在__init__这个构造函数中,添加了这个方法,目的是为了设置一个在__slots__中存在的属性的值,而在__setattr__函数中,我们重写了他,致使对任意类和实例属性进行修改的时候,都会进行异常抛出。
所以通过__setattr__,我们限制了实例属性“papapa”的任意修改。
如果对__slots__属性不理解的同学,推荐大家一个去处:
https://stackoverflow.com/questions/472000/usage-of-slots
写的很好。
目前我开了2个主群,我邀请了一些我的BAT伙伴前来助阵。定期也会在群里组织抽奖、送书等活动。更有各种资源分享。
目前2个主群都以过百,想要加入的小伙伴,可以加我微信,我拉你们,或者公众号回复关键“关注作者”。
另外:「高级群」已经升级啦!如果你错过了种子轮,难道还要错过天使轮吗?群内不定期组织红包接龙,每天中午1小时的随即话题讨论,没有广告,只聊技术、生活,这样的群上哪找?
用Python给程序加个进度条
浅尝Python快速排序
文章有问题?点此查看未经处理的缓存